Insights - Tabela de Dados da Aeronaútica

Introdução

A ideia desse documento é pegar um dataset com qual não tenho familiaridade e tentar extrair algum tipo de insight ou algum fato interessante usando R, usando especialmente data.table, Rmarkdown para compilar um documento de como fui me mergulhando nos dados junto com alguns htmlwidgets no caminho, e possivelmente criar um demo de um aplicativo shiny no final.

Nesse caso, escolhi um dataset que me interessou sobre Ocorrências Aeronáuticas na Aviação Civil Brasileira. Imagino que terá como mexer um pouco com mapas usando Leatlet ou alguma outra direção que quisermos tomar.

Esses datasets são extraídos da CENIPA e estão disponíveis no site de dados abertos do Governo Federal.

Segue uma breve descrição do que está no site:

A base de dados de ocorrências aeronáuticas é gerenciada pelo Centro de Investigação e Prevenção de Acidentes Aeronáuticos (CENIPA). Constam nesta base de dados as ocorrências aeronáuticas notificadas ao CENIPA nos últimos 10 anos e que ocorreram em solo brasileiro.

Dentre as informações disponíveis estão os dados sobre as aeronaves envolvidas, fatalidades, local, data, horário dos eventos e informações taxonômicas típicas das investigações de acidentes (AIG). São resguardadas a privacidade de pessoas físicas/jurídicas envolvidas conforme previsto pela Lei de Acesso à Informação (Lei n° 12.527, de 18 de novembro de 2011).

  • Informações dos dados utilizados nesse relatório:
Campo Valor
Fonte http://www.fab.mil.br/cenipa/
Autor Centro de Investigação e Prevenção de Acidentes Aeronáuticos
Mantenedor Centro de Investigação e Prevenção de Acidentes Aeronáuticos
Versão 1.3
Última Atualização 5 de Outubro de 2021, 19:19 (UTC-03:00)
Criado 1 de Junho de 2015, 15:37 (UTC-03:00)
Cobertura geográfica Brasil
Cobertura temporal 2010 a 2019
Fale Conosco
Frequência de atualização Anual
Granularidade geográfica Aeródromo
Granularidade temporal Hora:Minuto
VCGE Aeronáutica [http://vocab.e.gov.br/2011/03/vcge#aeronautica], Transporte Aéreo [http://vocab.e.gov.br/2011/03/vcge#transporte-aereo]

Importação e Tratamentos Iniciais dos Dados

Importação dos Dados

Bom, iniciei o programa importando as informações do portal da CENIPA (Centro de Investigação e Prevenção de Acidentes Aeronáuticos) encontrados no link mencionados na Introdução.

Note que se importarmos o programa sem especificar o encoding como “UTF-8”, então caracteres especiais do Português Brasil serão lidos incorretamente. e.g. “ã”, “é”, “Ç”, etc.

Cruzamento dos Dados

Explicação

Normalmente, essa seria um bom momento de dar uma olhada em algumas colunas e ver o que podemos fazer com elas. No entanto, lendo as informações no site de dados do Governo Federal, notei que apesar de termos 5 tabelas diferentes, há uma tabela “central” que possui informações adicionais distribuídas nas outras 4, assim como na imagem a seguir:

Relacionamento de dados das tabelas que usaremos Como as tabelas são bem pequenas, com menos 10 mil linhas e 30 colunas, cruzá-las e trazer todas as informações em um único dataset poderá facilitar o tratamento de dados mais para frente. Talvez fique um pouco mais difícil de ter uma panorama geral só batendo o olho, mas dado o número colunas parece ser algo tolerável.

Como estou usando o pacote data.table, utilizarei-o para cruzar as informações baseado na chave seguindo a imagem do relacionamento de dados das tabelas acima. Extraindo as informações da imagem acima, seria algo assim:

Cruzamento

Achados sobre a chave

Primeira coisa, dei um head para ter um panorama geral da tabela central, ocorrencia - especialmente das chaves. Nunca se sabe se algo deu errado.

head(ocorrencia[, c("codigo_ocorrencia", "codigo_ocorrencia1", "codigo_ocorrencia2", "codigo_ocorrencia3", "codigo_ocorrencia4")])
##    codigo_ocorrencia codigo_ocorrencia1 codigo_ocorrencia2 codigo_ocorrencia3
## 1:             40211              40211              40211              40211
## 2:             40349              40349              40349              40349
## 3:             40351              40351              40351              40351
## 4:             39527              39527              39527              39527
## 5:             40324              40324              40324              40324
## 6:             39807              39807              39807              39807
##    codigo_ocorrencia4
## 1:              40211
## 2:              40349
## 3:              40351
## 4:              39527
## 5:              40324
## 6:              39807

Opa! Olhando o header, parece que ocorreu algo peculiar. As 5 primeiras linhas das 5 chaves possuem o valor idêntico!

Note que isso não significa que todas as linhas serão iguais. Porém, há uma leve suspeita para saber se isso é muito mais que uma mera coincidência, ou seja, que realmente esteja assim na tabela inteira.

Para checarmos no R se as colunas possuem valores iguais, podemos usar a função identical para saber se os elementos são iguais.

identical(
  ocorrencia[, codigo_ocorrencia], 
  ocorrencia[, codigo_ocorrencia1], 
  ocorrencia[, codigo_ocorrencia2],
  ocorrencia[, codigo_ocorrencia3],
  ocorrencia[, codigo_ocorrencia4]
)
## [1] TRUE

E olha só! As colunas são de fato idênticas! Pode ser que um dia essas colunas sejam diferentes por algum motivo no site, mas no momento de nossa análise elas são idênticas.

Isso não mudará muita coisa no nosso cruzamento, mas isso significa que podemos descartar alguns dados mais para frente após o cruzamento.

Cruzando as tabelas

Voltando ao que interessa, vamos para o cruzamento. Tentarei fazer 4 left joins seguidos trazendo as informações das 4 tabelas complementares para a tabela central, ocorrencia:

cruzamento1 <- ocorrencia[ocorrencia_tipo, on = "codigo_ocorrencia1"] # Left Join 1
cruzamento2 <- cruzamento1[aeronave, on = "codigo_ocorrencia2"] # Left Join 2
cruzamento3 <- cruzamento2[fator_contribuinte, on = "codigo_ocorrencia3"] # Left Join 3
# tabela <- cruzamento3[recomendacao, on = "codigo_ocorrencia4"] # Left Join 4

Rodando o código acima sem a última linha estar comentada, obtive um erro vindo do último cruzamento, um left join entre ocorrencia e recomendacao:

Error in vecseq(f__, len, if (allow.cartesian || notjoin || !anyDuplicated(f, : Join results in 11387 rows; more than 6687 = nrow(x)+nrow(i). Check for duplicate key values in i each of which join to the same group in x over and over again. If that’s ok, try by=.EACHI to run j for each group to avoid the large allocation. If you are sure you wish to proceed, rerun with allow.cartesian=TRUE. Otherwise, please search for this error message in the FAQ, Wiki, Stack Overflow and data.table issue tracker for advice.

Será que são chaves mesmo?

Aparentemente as chaves de alguma das duas tabelas não são únicas. Vamos dar uma olhadinha na frequências das chaves (código de ocorrência - codigo_ocorrencia) das tabelas:

head(ocorrencia[, .(n = .N), by = codigo_ocorrencia][n > 1][order(-n)])
## Empty data.table (0 rows and 2 cols): codigo_ocorrencia,n
head(ocorrencia_tipo[, .(n = .N), by = codigo_ocorrencia1][n > 1][order(-n)])
##    codigo_ocorrencia1 n
## 1:              66444 3
## 2:              78780 3
## 3:              78879 3
## 4:              78904 3
## 5:              79620 3
## 6:              79651 3
head(aeronave[, .(n = .N), by = codigo_ocorrencia2][n > 1][order(-n)])
##    codigo_ocorrencia2 n
## 1:              45689 3
## 2:              78249 3
## 3:              79441 3
## 4:              41609 2
## 5:              43869 2
## 6:              44944 2
head(fator_contribuinte[, .(n = .N), by = codigo_ocorrencia3][n > 1][order(-n)])
##    codigo_ocorrencia3  n
## 1:              41053 19
## 2:              42250 19
## 3:              42921 19
## 4:              44660 18
## 5:              44796 18
## 6:              53340 17
head(recomendacao[, .(n = .N), by = codigo_ocorrencia4][n > 1][order(-n)])
##    codigo_ocorrencia4  n
## 1:              44796 23
## 2:              45554 20
## 3:              42250 19
## 4:              52265 13
## 5:              66432 12
## 6:              39992 11

Bom, dado que não há uma chave comum entre as tabelas que não estejam duplicadas, não é possível fazer um join simples entre elas como eu gostaria de ter feito. No entanto, como as tabelas não possuem nenhum campo de valor que poderíamos agregar (exceto 3 colunas que contém o nome “total” de frequência, mas que podem ser recalculadas usando as variáveis de origem), é possível fazer algo ainda que nos ajude a colocar tudo numa tabela só, usando cruzamento cartesiano (cartesian join).

Cruzamento Cartesiano

Fazer isso fará com que a tabela após os cruzamentos deixe de ter uma única chave, mas dado que irei sumarizar ela posteriormente com apenas uma seleção das colunas, deve dar tudo certo.

Então, para fazer o cruzamento cartesiano no data.table basta especificar o argumento no final. Vamos ver se agora dará certo…

cruzamento1 <- ocorrencia_tipo[ocorrencia, on = "codigo_ocorrencia1", allow.cartesian = TRUE] # Left Join 1
cruzamento2 <- aeronave[cruzamento1, on = "codigo_ocorrencia2", allow.cartesian = TRUE] # Left Join 2
cruzamento3 <- fator_contribuinte[cruzamento2, on = "codigo_ocorrencia3", allow.cartesian = TRUE] # Left Join 3
tabela <- recomendacao[cruzamento3, on = "codigo_ocorrencia4", allow.cartesian = TRUE] # Left Join 4

head(tabela)
##    codigo_ocorrencia4 recomendacao_numero recomendacao_dia_assinatura
## 1:              40211                <NA>                        <NA>
## 2:              40349                <NA>                        <NA>
## 3:              40351                <NA>                        <NA>
## 4:              39527                <NA>                        <NA>
## 5:              39527                <NA>                        <NA>
## 6:              39527                <NA>                        <NA>
##    recomendacao_dia_encaminhamento recomendacao_dia_feedback
## 1:                            <NA>                      <NA>
## 2:                            <NA>                      <NA>
## 3:                            <NA>                      <NA>
## 4:                            <NA>                      <NA>
## 5:                            <NA>                      <NA>
## 6:                            <NA>                      <NA>
##    recomendacao_conteudo recomendacao_status recomendacao_destinatario_sigla
## 1:                  <NA>                <NA>                            <NA>
## 2:                  <NA>                <NA>                            <NA>
## 3:                  <NA>                <NA>                            <NA>
## 4:                  <NA>                <NA>                            <NA>
## 5:                  <NA>                <NA>                            <NA>
## 6:                  <NA>                <NA>                            <NA>
##    recomendacao_destinatario codigo_ocorrencia3              fator_nome
## 1:                      <NA>              40211                    <NA>
## 2:                      <NA>              40349                    <NA>
## 3:                      <NA>              40351                    <NA>
## 4:                      <NA>              39527   APLICAÇÃO DE COMANDOS
## 5:                      <NA>              39527 JULGAMENTO DE PILOTAGEM
## 6:                      <NA>              39527     PLANEJAMENTO DE VOO
##               fator_aspecto  fator_condicionante        fator_area
## 1:                     <NA>                 <NA>              <NA>
## 2:                     <NA>                 <NA>              <NA>
## 3:                     <NA>                 <NA>              <NA>
## 4: DESEMPENHO DO SER HUMANO OPERAÇÃO DA AERONAVE FATOR OPERACIONAL
## 5: DESEMPENHO DO SER HUMANO OPERAÇÃO DA AERONAVE FATOR OPERACIONAL
## 6: DESEMPENHO DO SER HUMANO OPERAÇÃO DA AERONAVE FATOR OPERACIONAL
##    codigo_ocorrencia2 aeronave_matricula aeronave_operador_categoria
## 1:              40211              PRCHE                  TÁXI AÉREO
## 2:              40349              PRMAB                     REGULAR
## 3:              40351              PRMBW                     REGULAR
## 4:              39527              PTURT                         ***
## 5:              39527              PTURT                         ***
## 6:              39527              PTURT                         ***
##    aeronave_tipo_veiculo         aeronave_fabricante aeronave_modelo
## 1:           HELICÓPTERO           SIKORSKY AIRCRAFT           S-76C
## 2:                 AVIÃO            AIRBUS INDUSTRIE        A320-232
## 3:                 AVIÃO            AIRBUS INDUSTRIE        A319-132
## 4:                 AVIÃO NEIVA INDUSTRIA AERONAUTICA         EMB-202
## 5:                 AVIÃO NEIVA INDUSTRIA AERONAUTICA         EMB-202
## 6:                 AVIÃO NEIVA INDUSTRIA AERONAUTICA         EMB-202
##    aeronave_tipo_icao aeronave_motor_tipo aeronave_motor_quantidade
## 1:                S76           TURBOEIXO                   BIMOTOR
## 2:               A320                JATO                   BIMOTOR
## 3:               A319                JATO                   BIMOTOR
## 4:               IPAN              PISTÃO                 MONOMOTOR
## 5:               IPAN              PISTÃO                 MONOMOTOR
## 6:               IPAN              PISTÃO                 MONOMOTOR
##    aeronave_pmd aeronave_pmd_categoria aeronave_assentos
## 1:         5307                   5307                14
## 2:        70000                  70000               184
## 3:        75500                  75500               154
## 4:         1800                   1800                 1
## 5:         1800                   1800                 1
## 6:         1800                   1800                 1
##    aeronave_ano_fabricacao aeronave_pais_fabricante aeronave_pais_registro
## 1:                    2007                   BRASIL                 BRASIL
## 2:                    2001                   BRASIL                 BRASIL
## 3:                    2008                   BRASIL                 BRASIL
## 4:                    2004                   BRASIL                 BRASIL
## 5:                    2004                   BRASIL                 BRASIL
## 6:                    2004                   BRASIL                 BRASIL
##    aeronave_registro_categoria aeronave_registro_segmento
## 1:                 HELICÓPTERO                 TÁXI AÉREO
## 2:                       AVIÃO                    REGULAR
## 3:                       AVIÃO                    REGULAR
## 4:                       AVIÃO                 PARTICULAR
## 5:                       AVIÃO                 PARTICULAR
## 6:                       AVIÃO                 PARTICULAR
##         aeronave_voo_origem     aeronave_voo_destino aeronave_fase_operacao
## 1:        FORA DE AERODROMO        FORA DE AERODROMO              DECOLAGEM
## 2:        FORA DE AERODROMO        FORA DE AERODROMO              DECOLAGEM
## 3:        FORA DE AERODROMO        FORA DE AERODROMO          INDETERMINADA
## 4: FAZENDA IRMÃOS MUNARETTO FAZENDA IRMÃOS MUNARETTO     VOO A BAIXA ALTURA
## 5: FAZENDA IRMÃOS MUNARETTO FAZENDA IRMÃOS MUNARETTO     VOO A BAIXA ALTURA
## 6: FAZENDA IRMÃOS MUNARETTO FAZENDA IRMÃOS MUNARETTO     VOO A BAIXA ALTURA
##    aeronave_tipo_operacao aeronave_nivel_dano aeronave_fatalidades_total
## 1:             TÁXI AÉREO              NENHUM                          0
## 2:                REGULAR                LEVE                          0
## 3:                REGULAR                LEVE                          0
## 4:               AGRÍCOLA         SUBSTANCIAL                          0
## 5:               AGRÍCOLA         SUBSTANCIAL                          0
## 6:               AGRÍCOLA         SUBSTANCIAL                          0
##    codigo_ocorrencia1           ocorrencia_tipo
## 1:              40211             TRÁFEGO AÉREO
## 2:              40349           COLISÃO COM AVE
## 3:              40351           COLISÃO COM AVE
## 4:              39527 OPERAÇÃO A BAIXA ALTITUDE
## 5:              39527 OPERAÇÃO A BAIXA ALTITUDE
## 6:              39527 OPERAÇÃO A BAIXA ALTITUDE
##                              ocorrencia_tipo_categoria taxonomia_tipo_icao
## 1: PERDA DE SEPARAÇÃO / COLISÃO EM VOO | TRÁFEGO AÉREO                 MAC
## 2:                                     COLISÃO COM AVE                BIRD
## 3:                                     COLISÃO COM AVE                BIRD
## 4:                           OPERAÇÃO A BAIXA ALTITUDE                LALT
## 5:                           OPERAÇÃO A BAIXA ALTITUDE                LALT
## 6:                           OPERAÇÃO A BAIXA ALTITUDE                LALT
##    codigo_ocorrencia ocorrencia_classificacao ocorrencia_latitude
## 1:             40211                INCIDENTE                 ***
## 2:             40349                INCIDENTE                    
## 3:             40351                INCIDENTE                    
## 4:             39527                 ACIDENTE      -13.1066666667
## 5:             39527                 ACIDENTE      -13.1066666667
## 6:             39527                 ACIDENTE      -13.1066666667
##    ocorrencia_longitude  ocorrencia_cidade ocorrencia_uf ocorrencia_pais
## 1:                  ***     RIO DE JANEIRO            RJ          BRASIL
## 2:                                   BELÉM            PA          BRASIL
## 3:                          RIO DE JANEIRO            RJ          BRASIL
## 4:       -55.9930555556 LUCAS DO RIO VERDE            MT          BRASIL
## 5:       -55.9930555556 LUCAS DO RIO VERDE            MT          BRASIL
## 6:       -55.9930555556 LUCAS DO RIO VERDE            MT          BRASIL
##    ocorrencia_aerodromo ocorrencia_dia ocorrencia_hora
## 1:                 ****     03/01/2010        12:00:00
## 2:                 SBBE     03/01/2010        11:05:00
## 3:                 SBRJ     03/01/2010        03:00:00
## 4:                 ****     04/01/2010        17:30:00
## 5:                 ****     04/01/2010        17:30:00
## 6:                 ****     04/01/2010        17:30:00
##    investigacao_aeronave_liberada investigacao_status
## 1:                            SIM          FINALIZADA
## 2:                            SIM          FINALIZADA
## 3:                            SIM          FINALIZADA
## 4:                            SIM          FINALIZADA
## 5:                            SIM          FINALIZADA
## 6:                            SIM          FINALIZADA
##    divulgacao_relatorio_numero divulgacao_relatorio_publicado
## 1:                         ***                            NÃO
## 2:                                                        NÃO
## 3:                                                        NÃO
## 4:           A-539/CENIPA/2018                            SIM
## 5:           A-539/CENIPA/2018                            SIM
## 6:           A-539/CENIPA/2018                            SIM
##    divulgacao_dia_publicacao total_recomendacoes total_aeronaves_envolvidas
## 1:                      NULL                   0                          1
## 2:                      NULL                   0                          1
## 3:                      NULL                   0                          1
## 4:                2019-10-28                   0                          1
## 5:                2019-10-28                   0                          1
## 6:                2019-10-28                   0                          1
##    ocorrencia_saida_pista
## 1:                    NÃO
## 2:                    NÃO
## 3:                    NÃO
## 4:                    NÃO
## 5:                    NÃO
## 6:                    NÃO

E sucesso!

Wheeeew.

Agora que tenho uma tabela com todas as informações que preciso, posso criar algumas visões para tirar alguns insights ou análises interessantes sobre. Claro, após tratarmos alguns pontos dela :)

Tratamento dos Dados

Reordenação das Colunas

Para começar os tratamentos dos dados, reordenarei as colunas para ficar na ordem das bases que foram cruzadas, ou seja, na seguinte ordem:

  1. ocorrencia;
  2. ocorrencia_tipo;
  3. aeronave;
  4. fator_contribuinte;
  5. recomendacao;

Lembrando que como as colunas codigo_ocorrencia1, codigo_ocorrencia2, codigo_ocorrencia3, codigo_ocorrencia4 já existiam na tabela “central”, ocorrencia, irei removê-las para evitar algum tipo de mal entendido no vetor.

# Extrai o nome (e a ordem) das colunas pré cruzamento
colunas0 <- names(ocorrencia)
colunas1 <- names(ocorrencia_tipo)[2:length(names(ocorrencia_tipo))] # Eliminando a coluna de codigo_ocorrencia1
colunas2 <- names(aeronave)[2:length(names(aeronave))] # Eliminando a coluna de codigo_ocorrencia2
colunas3 <- names(fator_contribuinte)[2:length(names(fator_contribuinte))] # Eliminando a coluna de codigo_ocorrencia3
colunas4 <- names(recomendacao)[2:length(names(recomendacao))] # Eliminando a coluna de codigo_ocorrencia4

# Concatena os nomes das colunas
ordem_colunas <- c(colunas0, colunas1, colunas2, colunas3, colunas4)

# Atualiza a ordem na tabela por referência
data.table::setcolorder(tabela, ordem_colunas)

Conversão das Colunas

Após a ordenação, posso finalmente começar a dar uma olhada na tabela “analítica” (pós-cruzamento das tabelas) carinhosamente chamada de tabela. Vamos dar uma olhadinha:

str(tabela)
## Classes 'data.table' and 'data.frame':   17646 obs. of  59 variables:
##  $ codigo_ocorrencia              : int  40211 40349 40351 39527 39527 39527 39527 40324 39807 40215 ...
##  $ codigo_ocorrencia1             : int  40211 40349 40351 39527 39527 39527 39527 40324 39807 40215 ...
##  $ codigo_ocorrencia2             : int  40211 40349 40351 39527 39527 39527 39527 40324 39807 40215 ...
##  $ codigo_ocorrencia3             : int  40211 40349 40351 39527 39527 39527 39527 40324 39807 40215 ...
##  $ codigo_ocorrencia4             : int  40211 40349 40351 39527 39527 39527 39527 40324 39807 40215 ...
##  $ ocorrencia_classificacao       : chr  "INCIDENTE" "INCIDENTE" "INCIDENTE" "ACIDENTE" ...
##  $ ocorrencia_latitude            : chr  "***" "" "" "-13.1066666667" ...
##  $ ocorrencia_longitude           : chr  "***" "" "" "-55.9930555556" ...
##  $ ocorrencia_cidade              : chr  "RIO DE JANEIRO" "BELÉM" "RIO DE JANEIRO" "LUCAS DO RIO VERDE" ...
##  $ ocorrencia_uf                  : chr  "RJ" "PA" "RJ" "MT" ...
##  $ ocorrencia_pais                : chr  "BRASIL" "BRASIL" "BRASIL" "BRASIL" ...
##  $ ocorrencia_aerodromo           : chr  "****" "SBBE" "SBRJ" "****" ...
##  $ ocorrencia_dia                 : chr  "03/01/2010" "03/01/2010" "03/01/2010" "04/01/2010" ...
##  $ ocorrencia_hora                : chr  "12:00:00" "11:05:00" "03:00:00" "17:30:00" ...
##  $ investigacao_aeronave_liberada : chr  "SIM" "SIM" "SIM" "SIM" ...
##  $ investigacao_status            : chr  "FINALIZADA" "FINALIZADA" "FINALIZADA" "FINALIZADA" ...
##  $ divulgacao_relatorio_numero    : chr  "***" "" "" "A-539/CENIPA/2018" ...
##  $ divulgacao_relatorio_publicado : chr  "NÃO" "NÃO" "NÃO" "SIM" ...
##  $ divulgacao_dia_publicacao      : chr  "NULL" "NULL" "NULL" "2019-10-28" ...
##  $ total_recomendacoes            : int  0 0 0 0 0 0 0 0 0 0 ...
##  $ total_aeronaves_envolvidas     : int  1 1 1 1 1 1 1 1 1 1 ...
##  $ ocorrencia_saida_pista         : chr  "NÃO" "NÃO" "NÃO" "NÃO" ...
##  $ ocorrencia_tipo                : chr  "TRÁFEGO AÉREO" "COLISÃO COM AVE" "COLISÃO COM AVE" "OPERAÇÃO A BAIXA ALTITUDE" ...
##  $ ocorrencia_tipo_categoria      : chr  "PERDA DE SEPARAÇÃO / COLISÃO EM VOO | TRÁFEGO AÉREO" "COLISÃO COM AVE" "COLISÃO COM AVE" "OPERAÇÃO A BAIXA ALTITUDE" ...
##  $ taxonomia_tipo_icao            : chr  "MAC" "BIRD" "BIRD" "LALT" ...
##  $ aeronave_matricula             : chr  "PRCHE" "PRMAB" "PRMBW" "PTURT" ...
##  $ aeronave_operador_categoria    : chr  "TÁXI AÉREO" "REGULAR" "REGULAR" "***" ...
##  $ aeronave_tipo_veiculo          : chr  "HELICÓPTERO" "AVIÃO" "AVIÃO" "AVIÃO" ...
##  $ aeronave_fabricante            : chr  "SIKORSKY AIRCRAFT" "AIRBUS INDUSTRIE" "AIRBUS INDUSTRIE" "NEIVA INDUSTRIA AERONAUTICA" ...
##  $ aeronave_modelo                : chr  "S-76C" "A320-232" "A319-132" "EMB-202" ...
##  $ aeronave_tipo_icao             : chr  "S76" "A320" "A319" "IPAN" ...
##  $ aeronave_motor_tipo            : chr  "TURBOEIXO" "JATO" "JATO" "PISTÃO" ...
##  $ aeronave_motor_quantidade      : chr  "BIMOTOR" "BIMOTOR" "BIMOTOR" "MONOMOTOR" ...
##  $ aeronave_pmd                   : int  5307 70000 75500 1800 1800 1800 1800 11990 726 18600 ...
##  $ aeronave_pmd_categoria         : int  5307 70000 75500 1800 1800 1800 1800 11990 726 18600 ...
##  $ aeronave_assentos              : chr  "14" "184" "154" "1" ...
##  $ aeronave_ano_fabricacao        : chr  "2007" "2001" "2008" "2004" ...
##  $ aeronave_pais_fabricante       : chr  "BRASIL" "BRASIL" "BRASIL" "BRASIL" ...
##  $ aeronave_pais_registro         : chr  "BRASIL" "BRASIL" "BRASIL" "BRASIL" ...
##  $ aeronave_registro_categoria    : chr  "HELICÓPTERO" "AVIÃO" "AVIÃO" "AVIÃO" ...
##  $ aeronave_registro_segmento     : chr  "TÁXI AÉREO" "REGULAR" "REGULAR" "PARTICULAR" ...
##  $ aeronave_voo_origem            : chr  "FORA DE AERODROMO" "FORA DE AERODROMO" "FORA DE AERODROMO" "FAZENDA IRMÃOS MUNARETTO" ...
##  $ aeronave_voo_destino           : chr  "FORA DE AERODROMO" "FORA DE AERODROMO" "FORA DE AERODROMO" "FAZENDA IRMÃOS MUNARETTO" ...
##  $ aeronave_fase_operacao         : chr  "DECOLAGEM" "DECOLAGEM" "INDETERMINADA" "VOO A BAIXA ALTURA" ...
##  $ aeronave_tipo_operacao         : chr  "TÁXI AÉREO" "REGULAR" "REGULAR" "AGRÍCOLA" ...
##  $ aeronave_nivel_dano            : chr  "NENHUM" "LEVE" "LEVE" "SUBSTANCIAL" ...
##  $ aeronave_fatalidades_total     : int  0 0 0 0 0 0 0 0 0 0 ...
##  $ fator_nome                     : chr  NA NA NA "APLICAÇÃO DE COMANDOS" ...
##  $ fator_aspecto                  : chr  NA NA NA "DESEMPENHO DO SER HUMANO" ...
##  $ fator_condicionante            : chr  NA NA NA "OPERAÇÃO DA AERONAVE" ...
##  $ fator_area                     : chr  NA NA NA "FATOR OPERACIONAL" ...
##  $ recomendacao_numero            : chr  NA NA NA NA ...
##  $ recomendacao_dia_assinatura    : IDate, format: NA NA ...
##  $ recomendacao_dia_encaminhamento: IDate, format: NA NA ...
##  $ recomendacao_dia_feedback      : chr  NA NA NA NA ...
##  $ recomendacao_conteudo          : chr  NA NA NA NA ...
##  $ recomendacao_status            : chr  NA NA NA NA ...
##  $ recomendacao_destinatario_sigla: chr  NA NA NA NA ...
##  $ recomendacao_destinatario      : chr  NA NA NA NA ...
##  - attr(*, ".internal.selfref")=<externalptr>

Hmm…

Analisando com calma a tabela, podemos anotar alguns pontos estranhos:

  • De cara, dá para ver algumas colunas que não eram para ser texto: aeronave_ano_fabricacao, ocorrencia_latitude, ocorrencia_dia, etc;
    • Não appenas isso: dentre essas colunas, algumas precisam ser convertidas para número enquanto outras para data;
  • Além disso, nossa tabela possui alguns valores estranhos como “***“,”NULL” (literalmente como texto, não como valor booleano), que irei inferir que são Missing já que não possuo metadados sobre o dataset.

Como os valores missing influenciará na conversão dos dados de texto para outros tipos, então começarei tratando eles primeiro.

Corrigindo os valores missing

Para corrigir os valores missing das colunas que são do tipo Texto, primeiro:

  • Filtramos todas as colunas que são texto;

  • E depois, caso algum elemento se encaixe em alguns dos valores estranhos que vimos, transformamos em missing (NA). e.g. “***“,”NULL”, etc.

Então, temos:

# Seleciona as colunas que são do tipo character (texto), e guarda na colunas_texto
indices_colunas_texto <- which(unlist(lapply(tabela, is.character)))
colunas_texto <- names(tabela)[indices_colunas_texto]

# Para cada coluna do colunas_texto, troca o valor estranho para missing (NA) usando ifelse
tabela[, (colunas_texto) := lapply(.SD, function(x) ifelse(
  x == "***" 
  | x == "****" 
  | x == "*****"
  | x == "******"
  | x == "*******"
  | x == "********"
  | x == "*********"
  | x == "****_***"
  | x == "****_****"
  | x == "NULL" 
  | x == "", 
  NA, x)), .SDcols = colunas_texto]

Texto para datas

As colunas que deveriam ser do tipo Data contém “dia” no nome:

names(tabela)[grepl("*dia", names(tabela))]
## [1] "ocorrencia_dia"                  "divulgacao_dia_publicacao"      
## [3] "recomendacao_dia_assinatura"     "recomendacao_dia_encaminhamento"
## [5] "recomendacao_dia_feedback"
de_texto_para_data <- names(tabela)[grepl("*dia", names(tabela))]
str(tabela[, ..de_texto_para_data])
## Classes 'data.table' and 'data.frame':   17646 obs. of  5 variables:
##  $ ocorrencia_dia                 : chr  "03/01/2010" "03/01/2010" "03/01/2010" "04/01/2010" ...
##  $ divulgacao_dia_publicacao      : chr  NA NA NA "2019-10-28" ...
##  $ recomendacao_dia_assinatura    : IDate, format: NA NA ...
##  $ recomendacao_dia_encaminhamento: IDate, format: NA NA ...
##  $ recomendacao_dia_feedback      : chr  NA NA NA NA ...
##  - attr(*, ".internal.selfref")=<externalptr>

Logo, para converter, basta aplicarmos o as.IDate - que é essencialmente o Date normal do R, mas compatível com o data.table.

Só um ponto de atenção: a variável ocorrencia_dia não só está como texto quanto também está em um formato de data diferente das demais. Tirando isso, as coisas estão dando tudo certo!

# Converte somente a coluna ocorrencia_dia por ter um formato diferente (DD/MM/YYYY) 
tabela[, ocorrencia_dia := as.IDate(ocorrencia_dia, "%d/%m/%Y")]

# Converte colunas que possuem o formato (YYYY-MM-DD) 
tabela[, `:=`(
  divulgacao_dia_publicacao = as.IDate(divulgacao_dia_publicacao, "%Y-%m-%d"),
  recomendacao_dia_assinatura = as.IDate(recomendacao_dia_assinatura, "%Y-%m-%d"),
  recomendacao_dia_encaminhamento = as.IDate(recomendacao_dia_encaminhamento, "%Y-%m-%d"),
  recomendacao_dia_feedback = as.IDate(recomendacao_dia_feedback, "%Y-%m-%d")
)]

# Converte a coluna ocorrencia_hora para o formato ITime 
tabela[, ocorrencia_hora := as.ITime(ocorrencia_hora, "%d/%m/%Y")]

Texto para numérico/inteiro

Agora para o caso de ver qual variável deveria ser numérica, não tem jeito. Como o número é pequeno, dá para darmos uma olhada olhando no “str(tabela)” acima.

  • ocorrencia_latitude;
  • ocorrencia_longitude;
  • aeronave_assentos;
  • aeronave_ano_fabricacao;

Sabendo quais são as colunas, basta convertê-las:

colunas_texto_para_numero <- c(
"ocorrencia_latitude",
"ocorrencia_longitude",
"aeronave_assentos",
"aeronave_ano_fabricacao"
)

# tabela[, (colunas_texto_para_numero) := lapply(.SD, function(x) as.numeric(x)), .SDcols = colunas_texto_para_numero]

Ou pelo menos deveria ser! Tentando converter as 4 colunas de uma vez retorna erro em 2 colunas - que estão aplicando NA por coercion, ou seja, por não saber converter. Olhando mais afundo, notamos que o problema ocorre nas colunas de latitude e longitude. Portanto, vamos converter as outras duas que deram certo, aeronave_assentos e aeronave_assentos, e ver mais a fundo o caso do da latitude e longitude.

tabela[, `:=`(
  aeronave_assentos = as.numeric(aeronave_assentos),
  aeronave_ano_fabricacao = as.numeric(aeronave_ano_fabricacao)
)]

Latitude e Longitude

Texto

Astericos
# Observações que ainda possuem asteriscos
unique(tabela$ocorrencia_latitude)[grepl("\\*", unique(tabela$ocorrencia_latitude))]
## [1] "***-22.98575784" "-14.71083***"
# Observações que ainda possuem asteriscos
unique(tabela$ocorrencia_longitude)[grepl("\\*", unique(tabela$ocorrencia_longitude))]
## character(0)
Coordenadas em outro sistema (como DMS - Decimal degrees, minutes and seconds)
tabela[ocorrencia_latitude %like% "”", ocorrencia_latitude]
## [1] "15° 39’ 00”S" "15° 39’ 00”S"
tabela[ocorrencia_longitude %like% "”", ocorrencia_longitude]
## [1] "056° 07’ 03” W" "056° 07’ 03” W"
Outros casos peculiares
head(sort(unique(tabela[, ocorrencia_latitude])), 135)
##   [1] "- 22.75944"      "-0,889722"       "-0.0"            "-0.0075"        
##   [5] "-0.050833333333" "-0.0911111111"   "-0.2002777778"   "-0.2827778"     
##   [9] "-0.3061111111"   "-0.7333333333"   "-0.8669444444"   "-0.985"         
##  [13] "-0.9880555556"   "-00.0000"        "-01.43778"       "-01.5325"       
##  [17] "-03.76472"       "-04.1650"        "-04.87139"       "-05.05972222"   
##  [21] "-05.2850"        "-05.530555"      "-07.04028"       "-07.2191666"    
##  [25] "-08.12638"       "-08.126388"      "-08.1263888"     "-08.12638888"   
##  [29] "-08.12639"       "-08.271666"      "-08.713611"      "-08.84917"      
##  [33] "-08.9594444"     "-09.53432276"    "-09.868888"      "-09.96583"      
##  [37] "-1,3708"         "-1,3808"         "-1.0870555555"   "-1.144722"      
##  [41] "-1.1966666667"   "-1.2388888889"   "-1.2941666667"   "-1.3333333333"  
##  [45] "-1.3611111111"   "-1.38000"        "-1.3801422"      "-1.380277777777"
##  [49] "-1.38472"        "-1.3847222222"   "-1.384722222222" "-1.38556"       
##  [53] "-1.3858333333"   "-1.3916666667"   "-1.3927777778"   "-1.4077777778"  
##  [57] "-1.4119444444"   "-1.41444"        "-1.4144444444"   "-1.415"         
##  [61] "-1.41500"        "-1.415000"       "-1.4169444444"   "-1.419722222"   
##  [65] "-1.4361111111"   "-1.437777777777" "-1.4452777778"   "-1.46472"       
##  [69] "-1.4886111111"   "-1.532923792"    "-1.5922222222"   "-1.6386111111"  
##  [73] "-1.65000"        "-1.7213888889"   "-1.775"          "-1.797777777777"
##  [77] "-1.9536111111"   "-1.955833"       "-1.9813888889"   "-10.0061111111" 
##  [81] "-10.011389"      "-10.017222222"   "-10.058333"      "-10.0619444444" 
##  [85] "-10.0672222222"  "-10.081667"      "-10.1025"        "-10.10806"      
##  [89] "-10.182778"      "-10.183889"      "-10.188187"      "-10.19250"      
##  [93] "-10.2680555556"  "-10.29"          "-10.290000"      "-10.2900000"    
##  [97] "-10.2916666667"  "-10.2961111111"  "-10.296389"      "-10.3772222222" 
## [101] "-10.4144444444"  "-10.422500"      "-10.4908333333"  "-10.4933333333" 
## [105] "-10.5261111111"  "-10.5305555556"  "-10.5972222222"  "-10.6002777778" 
## [109] "-10.6336111111"  "-10.656111"      "-10.7275"        "-10.7297222222" 
## [113] "-10.7338888889"  "-10.7405555556"  "-10.7555555556"  "-10.7641666667" 
## [117] "-10.7691666667"  "-10.804722"      "-10.870556"      "-10.8875"       
## [121] "-10.8883333333"  "-10.9033333333"  "-10.927500"      "-10.94"         
## [125] "-10.94361"       "-10.9583333333"  "-10.98472"       "-10.9852777778" 
## [129] "-10.991111"      "-100.6775"       "-101.827.777.77" "-102.833.333.33"
## [133] "-102.961.111.11" "-103.452.777.77" "-11.009317"
head(sort(unique(tabela[, ocorrencia_longitude])), 40)
##  [1] "--49.0324242"    "--49.239174323"  "- 40.68583"      "-0.0"           
##  [5] "-00.0000"        "-1000.6775"      "-18.2250"        "-18.83916"      
##  [9] "-20.4230"        "-23.18166666666" "-25.40555555555" "-32.9919444444" 
## [13] "-34.83833"       "-34.8425"        "-34.85"          "-34.87833333"   
## [17] "-34.8913888889"  "-34.89138889"    "-34.8916666667"  "-34.9005555556" 
## [21] "-34.92277"       "-34.922777"      "-34.92277777"    "-34.922777777"  
## [25] "-34.9227777777"  "-34.92277777777" "-34.9227777778"  "-34.92277778"   
## [29] "-34.92278"       "-34.927262"      "-34.9447222222"  "-34.95027"      
## [33] "-34.9502777778"  "-34.9505555555"  "-348.425"        "-348.452.777.77"
## [37] "-348.913.888.88" "-349.127.777.77" "-349.227.777.77" "-349.502.777.77"
tail(sort(unique(tabela[, ocorrencia_longitude])), 55)
##  [1] "-727.694.444.44" "-727.797.222.22" "-8.00872"        "000"            
##  [5] "042.4241"        "051,13666"       "056° 07’ 03” W"  "11.8666666667"  
##  [9] "14.98400"        "16,6372222"      "3.0808333333"    "34.9094444444"  
## [13] "35.5838888889"   "38.5322222222"   "41.06833"        "413.077.777.778"
## [17] "43.98916667"     "432.505.555.556" "439.505.555.556" "444.216.666.667"
## [21] "45.8922222222"   "46.473055555556" "46.633888888889" "46.6563888889"  
## [25] "46.8180555556"   "46.9047222222"   "46.9436111111"   "465.741.666.667"
## [29] "466.341.666.667" "47.0577777778"   "47.2680555556"   "47.9186111111"  
## [33] "48.022222222222" "48.458275"       "48.5958333333"   "487.575"        
## [37] "488.166.666.667" "49.226667"       "49.2286"         "49.3988888889"  
## [41] "49.4686111111"   "49.5147222222"   "493.494.444.444" "50.0158333333"  
## [45] "51.2038888889"   "512.880.555.556" "52.685"          "53.5522222222"  
## [49] "54.4922222222"   "54.7241666667"   "55.6725"         "56.5230555556"  
## [53] "63.9027777778"   "Longitude: -43." "Longitude: -47."

Texto…

Texto 2…

### Caso 1 - Espaço, e.g. "- 22.75944"
tabela[, ocorrencia_latitude := gsub(" ", "", ocorrencia_latitude)]
tabela[, ocorrencia_longitude := gsub(" ", "", ocorrencia_longitude)]

### Caso 2 - Vírgula, e.g. "-0,889722"
tabela[, ocorrencia_latitude := gsub(",", ".", ocorrencia_latitude)]
tabela[, ocorrencia_longitude := gsub(",", ".", ocorrencia_longitude)]

### Caso 3 - Duplo negativo, e.g. "--49.0324242"
tabela[, ocorrencia_latitude := gsub("--", "-", ocorrencia_latitude)]
tabela[, ocorrencia_longitude := gsub("--", "-", ocorrencia_longitude)]

### Caso 4 - Com a palavra Latitude/Longitude na frente, e.g. "Longitude:-47."
tabela[ocorrencia_latitude %like% "Latitude", ocorrencia_latitude := gsub("Latitude:", "", ocorrencia_latitude)]
tabela[ocorrencia_longitude %like% "Longitude", ocorrencia_longitude := gsub("Longitude:", "", ocorrencia_longitude)]

### Caso 5 - Coordenada em DMS - Decimal degrees, minutes and seconds
tabela[ocorrencia_latitude == "15°39’00”S", ocorrencia_latitude := "-15.650000"]
tabela[ocorrencia_longitude == "056°07’03”W", ocorrencia_longitude := "-56.117500"]

### Caso 6 - Asteriscos na frente ou atrás do número (só Lat)
tabela[ocorrencia_latitude == "***-22.98575784", ocorrencia_latitude := "-22.98575784"]
tabela[ocorrencia_latitude == "-14.71083***", ocorrencia_latitude := "-14.71083"]

### Caso 7 - Possui/termina com S, N, W, ou E, mas não está formatado em coordenadas DMS como no Caso 5
tabela[, ocorrencia_latitude := gsub("S", "", ocorrencia_latitude)]
tabela[, ocorrencia_latitude := gsub("N", "", ocorrencia_latitude)]
tabela[, ocorrencia_longitude := gsub("W", "", ocorrencia_longitude)]
tabela[, ocorrencia_longitude := gsub("E", "", ocorrencia_longitude)]

### Caso 8 - Possui/termina com o símbolo de Grau ("º"/"°")
tabela[, ocorrencia_latitude := gsub("°", "", ocorrencia_latitude)]
tabela[, ocorrencia_longitude := gsub("°", "", ocorrencia_longitude)]

tabela_ <- data.table::copy(tabela)

### Caso 9 - Número cheio de separadores usando ponto ("."). (Lat e Log)
# Cria flag marcando casos que possíveis não estão todos corretos
tabela[, flag_lat_long := fifelse(
    lengths(regmatches(ocorrencia_latitude, gregexpr("\\.", ocorrencia_latitude))) > 1
    | lengths(regmatches(ocorrencia_longitude, gregexpr("\\.", ocorrencia_longitude))) > 1,
    FALSE,
    TRUE
  )
]

# Latitude
tabela[
  lengths(regmatches(ocorrencia_latitude, gregexpr("\\.", ocorrencia_latitude))) > 1, 
  ocorrencia_latitude := fifelse(
    as.numeric(gsub("\\.", "", ocorrencia_latitude)) > 0, 
    sub("(.{2})(.*)", "\\1.\\2", gsub("\\.", "", ocorrencia_latitude)), 
    sub("(.{3})(.*)", "\\1.\\2", gsub("\\.", "", ocorrencia_latitude))
  )
]

# Longitude
tabela[
  lengths(regmatches(ocorrencia_longitude, gregexpr("\\.", ocorrencia_longitude))) > 1, 
  ocorrencia_longitude := fifelse(
    as.numeric(gsub("\\.", "", ocorrencia_longitude)) > 0, 
    sub("(.{2})(.*)", "\\1.\\2", gsub("\\.", "", ocorrencia_longitude)), 
    sub("(.{3})(.*)", "\\1.\\2", gsub("\\.", "", ocorrencia_longitude))
  )
]

### Após tratamentos, FINALMENTE converte as colunas para numérico
tabela[, `:=`(
  ocorrencia_latitude = as.numeric(ocorrencia_latitude),
  ocorrencia_longitude = as.numeric(ocorrencia_longitude)
)]

### Caso 10 - 44993 e 50794 não possuem longitude
# Como a ocorrencia 44993 foi na cidade do Rio de Janeiro, aproxima usando as coordenadas
# do Aeroporto Doméstico Santos Dumont: -22.90825417333246, -43.16789880589976
tabela[codigo_ocorrencia == 44993, ocorrencia_longitude := -43.16789880589976]

# Como a ocorrencia 50794 foi na cidade de Turmalina, MG, aproxima usando as coordenadas
# do ponto zero da cidade: -17.285824901708047, -42.731887838264434
tabela[codigo_ocorrencia == 50794, ocorrencia_longitude := -42.731887838264434]

Após tratamentos:

head(sort(unique(tabela[, ocorrencia_latitude])), 135)
##   [1] -2.623500e+07 -2.970250e+02 -2.626750e+02 -2.350750e+02 -2.298750e+02
##   [6] -2.292750e+02 -2.282250e+02 -2.229750e+02 -2.044250e+02 -2.043750e+02
##  [11] -1.738250e+02 -1.670250e+02 -1.636250e+02 -1.586250e+02 -1.585250e+02
##  [16] -1.565250e+02 -1.006775e+02 -9.868889e+01 -9.587500e+01 -9.517222e+01
##  [21] -9.367500e+01 -9.256111e+01 -9.228333e+01 -9.033333e+01 -8.959444e+01
##  [26] -8.713611e+01 -8.590556e+01 -8.566667e+01 -8.126389e+01 -8.116944e+01
##  [31] -8.038333e+01 -7.844444e+01 -7.821389e+01 -7.599444e+01 -7.502500e+01
##  [36] -7.398400e+01 -7.358333e+01 -7.229167e+01 -7.160556e+01 -7.148333e+01
##  [41] -7.091944e+01 -7.089444e+01 -7.046389e+01 -6.823611e+01 -6.818889e+01
##  [46] -6.763889e+01 -6.763056e+01 -6.693056e+01 -6.540278e+01 -6.529167e+01
##  [51] -6.086944e+01 -5.908611e+01 -5.868333e+01 -5.368056e+01 -5.248805e+01
##  [56] -5.238222e+01 -5.146111e+01 -5.050556e+01 -4.923389e+01 -4.921167e+01
##  [61] -4.874444e+01 -4.871389e+01 -4.848056e+01 -4.720278e+01 -4.694361e+01
##  [66] -4.519050e+01 -4.250556e+01 -4.244444e+01 -4.162500e+01 -4.074167e+01
##  [71] -4.033250e+01 -3.775833e+01 -3.708333e+01 -3.509167e+01 -3.497941e+01
##  [76] -3.343667e+01 -3.343639e+01 -3.338472e+01 -3.326889e+01 -3.317694e+01
##  [81] -3.314611e+01 -3.249611e+01 -3.244361e+01 -3.241556e+01 -3.240972e+01
##  [86] -3.238167e+01 -3.228833e+01 -3.227361e+01 -3.226722e+01 -3.225583e+01
##  [91] -3.222194e+01 -3.217611e+01 -3.214972e+01 -3.208167e+01 -3.206444e+01
##  [96] -3.198472e+01 -3.196222e+01 -3.193583e+01 -3.171722e+01 -3.158278e+01
## [101] -3.145139e+01 -3.142278e+01 -3.124361e+01 -3.119389e+01 -3.117111e+01
## [106] -3.115528e+01 -3.113153e+01 -3.105167e+01 -3.104111e+01 -3.103361e+01
## [111] -3.102250e+01 -3.099111e+01 -3.090306e+01 -3.087806e+01 -3.084472e+01
## [116] -3.084361e+01 -3.083944e+01 -3.083694e+01 -3.078556e+01 -3.077556e+01
## [121] -3.073056e+01 -3.072778e+01 -3.066194e+01 -3.060556e+01 -3.053806e+01
## [126] -3.050861e+01 -3.047472e+01 -3.044944e+01 -3.044083e+01 -3.041111e+01
## [131] -3.038889e+01 -3.038333e+01 -3.036083e+01 -3.024917e+01 -3.024556e+01
head(sort(unique(tabela[, ocorrencia_longitude])), 40)
##  [1] -6.013827e+10 -4.819457e+08 -1.000678e+03 -6.689750e+02 -6.006250e+02
##  [6] -5.633750e+02 -5.611750e+02 -5.434750e+02 -5.430750e+02 -5.226250e+02
## [11] -5.215750e+02 -5.108250e+02 -5.102750e+02 -5.064750e+02 -4.950750e+02
## [16] -4.855250e+02 -4.599750e+02 -4.583750e+02 -4.502250e+02 -4.501250e+02
## [21] -4.316250e+02 -3.832250e+02 -3.484250e+02 -7.278111e+01 -7.277972e+01
## [26] -7.277972e+01 -7.277972e+01 -7.276944e+01 -7.276944e+01 -7.274528e+01
## [31] -7.270556e+01 -7.168833e+01 -7.168833e+01 -7.164860e+01 -7.048278e+01
## [36] -7.048278e+01 -7.015194e+01 -7.011417e+01 -7.009389e+01 -7.002528e+01
tail(sort(unique(tabela[, ocorrencia_longitude])), 40)
##  [1]  41.30778  42.42410  43.25056  43.95056  43.98917  44.42167  45.89222
##  [8]  46.47306  46.57417  46.63389  46.63417  46.65639  46.81806  46.90472
## [15]  46.94361  47.05778  47.26806  47.91861  48.02222  48.45828  48.59583
## [22]  48.81667  49.22667  49.22860  49.34944  49.39889  49.46861  49.51472
## [29]  50.01583  51.13666  51.20389  51.28806  52.68500  53.55222  54.49222
## [36]  54.72417  55.67250  56.52306  63.90278 487.57500

Após tratamentos…


Análises

Em construção, maybe

Número de ocorrências pelo tempo

Calendário

# Seleciona as colunas relevantes, e dá um distinct para evitar observações duplicadas
ocorrencias_tempo_prep <- unique(tabela[, .(ocorrencia_dia, codigo_ocorrencia)])

# 
ocorrencias_tempo <- ocorrencias_tempo_prep[, .(N = .N, ocorrencia_ano = as.character(year(ocorrencia_dia))), keyby = c("ocorrencia_dia")]

ocorrencias_tempo |> 
  e_charts(ocorrencia_dia)|> 
  e_calendar(
    range = c(min(ocorrencias_tempo$ocorrencia_ano), max(ocorrencias_tempo$ocorrencia_ano)),
    # orient = "vertical",
    # width = 1,
    left = "2.5%",
    #top = "15%",
    dayLabel = list(show = F),
    yearLabel = list(show = F)
    ) |> 
  e_heatmap(N, coord_system = "calendar") |> 
  e_visual_map(max = max(ocorrencias_tempo$N)) |>  
  e_theme("essos") |>  
  e_title("Calendar", "Heatmap")

Ano a Ano

ocorrencias_tempo[, .(Ocorrências = sum(N)), keyby = ocorrencia_ano] |>  
  e_charts(ocorrencia_ano) |>  
  e_line(Ocorrências) |>  
  e_theme("chalk") |>  
  e_title("Número de Ocorrências - Ano a ano") |> 
  e_tooltip(trigger = "axis")  

Tabela

reactable::reactable(ocorrencias_tempo[, .(N = sum(N)), keyby = ocorrencia_ano])